module Orator

  # Handles the server connections and passing stuff to the event handler.
  class Server

    # The options defined for the server.
    #
    # @return [Hash]
    attr_reader :options

    # The list of clients that are connected.
    #
    # @return [Set<Client>]
    attr_reader :clients

    # The event handler that is duplicated for every client.  This is to reduce
    # the overhead of reinitializing the event handler for every client.
    #
    # @return [EventHandler]
    attr_reader :event_handler

    # Initialize the server.
    #
    # @return [void]
    def initialize(options)
      @options = options
      @clients = Set.new
    end

    # Runs the server with the given options.
    def run(router, &block)
      @event_handler = EventHandler.new(router, &block)
      EM::WebSocket.start(@options, &method(:handle_socket))
    end

    private

    # Handles setting up the socket.  This binds the [#onopen], [#onclose],
    # [#onerror], and [#onmessage] events.
    #
    # @param [Object]
    def handle_socket(socket)
      client = Client.new :event_handler => @event_handler.dup,
        :socket => socket, :context => nil
      client.context = MiddleGround.new(client, clients)
      clients << client

      socket.onopen do |handshake|
        client.trigger 'socket.open', handshake
      end

      socket.onerror do |error|
        client.trigger 'socket.error', error
      end

      socket.onclose do |message|
        client.trigger 'socket.close', message
        clients.delete client
      end

      socket.onmessage do |data|
        json_data = Oj.load data, :mode => :null
        client.trigger json_data["event"], json_data
      end

    end

  end

end
